Load required libraries

library(tidyverse)
library(here)
library(brms)
library(tidybayes)
library(sf)
library(mgcv)
library(priorsense)
library(osmdata)
library(nngeo) 

Air quality data

By summary, a random household survey was conducted in Blantyre Malawi during 2019-2020 (pre-COVID in Malawi) as part of a TB cluster randomised trial pre-intervention prevalence survey (sumamrised here: https://europepmc.org/article/MED/37862284). Fieldworkers carried purple air monitors attached to their backpacks, with measurements set to read every 90 seconds. Not all fieldworkers had a monitor. Previously, Helen Savage cleaned these monitor data, and merged to household questionnaire data, filtering measurements by interview times. Therefore, measurements are indoor household measurements.

Cluster boundaries (72 in total) are based on Ministry of Health Community Health Worker catchment areas, refined in collaboration with researchers. These were the unit of randomisation for the SCALE cluster randomised trial.

All air quality measurements were then taken from households within the 72 SCALE cluster.

load("input_data/aq_in.RData")
#input the scale clusters
load("input_data/scale_72_clusters.rda")

Get data into correct shape and aggregate measurements per household. Note as purple air devices took measurements every 90 seconds, mostly housholds surveyed have multiple measurements. Here, for convenience, we take the mean of these measurement per household.

Covariates

Population counts and density

#fix the coordinate crs of the scale clusters
scale_72_clusters <-  st_transform(scale_72_clusters, st_crs(mw_100m))
old-style crs object detected; please recreate object with a recent sf::st_crs()

Building density (i.e. we get the building footprints, and calculate their combined footprint area per grid cell, then calculate what percentage of the grid cell is “building footprint”) https://sites.research.google/gr/open-buildings/#open-buildings-download

Using Version 2 here - can update later to V3, with better precision, and year-specific data. (I think this is for 2020 currently)


#read in the data set
#is a stars dataset
buildings <- read_rds("input_data/blantyre_buff_buildings.rds")

#match the crs to the population data
buildings <-  st_transform(buildings, st_crs(mw_100m))

#convert stars object to polygons
mw_100m_grid_sf <- st_as_sf(mw_100m_cropped, as_points = FALSE, merge = FALSE)

#add grid cell ID for grouping
mw_100m_grid_sf <- mw_100m_grid_sf %>%
  mutate(grid_id = row_number())

#join building footprint data to the population data
buildings_with_grid <- st_join(buildings, mw_100m_grid_sf, left = FALSE)

#filter by confidence of building footprint, and by footprint size
#in Hannah R's previous experiements, this was a good compromise
#and matches well with home visits on the ground.
buildings_with_grid <- buildings_with_grid %>%
  filter(area_in_meters>20) %>%
  filter(area_in_meters<300) %>%
  filter(confidence>0.69)

#sum building footprint per grid cell
building_area_per_cell <- buildings_with_grid %>%
  group_by(grid_id) %>%
  summarise(total_building_area_m2 = sum(area_in_meters, na.rm = TRUE))

#cell area in m squared
cell_area_m2 <- 100 * 100

#compute percentage coverage
building_area_per_cell <- building_area_per_cell %>%
  mutate(building_coverage_pct = (total_building_area_m2 / cell_area_m2) * 100)

#join
mw_100m_grid_sf <- mw_100m_grid_sf %>%
  left_join(building_area_per_cell %>% st_drop_geometry(), by = "grid_id") %>%
  mutate(building_coverage_pct = replace_na(building_coverage_pct, 0))

#check by plotting
mw_100m_grid_sf %>%
  mutate(x = st_coordinates(st_centroid(.))[, 1],
         y = st_coordinates(st_centroid(.))[, 2]) %>%
  ggplot() +
  geom_tile(aes(x=x, y=y, fill=building_coverage_pct)) +
  scale_fill_viridis_c(option = "cividis") +
  theme_ggdist() +
  theme(panel.background = element_rect(colour = "grey78"))

Distance to the nearest main road. I.e. because we think that PM2.5 exposure can come from road vehicles.

We use Open Street Map (OSM) data to get the main roads (there are few of these in Blantyre… but see the most traffic). Later could consider including some smaller road…

#check plot
mw_100m_grid_sf %>%
  mutate(x = st_coordinates(st_centroid(.))[, 1],
         y = st_coordinates(st_centroid(.))[, 2]) %>%
  ggplot() +
  geom_tile(aes(x=x, y=y, fill=dist_to_road_m)) +
  scale_fill_viridis_c(option = "G", direction = -1) +
  theme(panel.background = element_rect(colour = "grey78")) +
  theme_ggdist() +
  theme(panel.background = element_rect(colour = "grey78"))
Warning: There were 2 warnings in `stopifnot()`.
The first warning was:
ℹ In argument: `x = st_coordinates(st_centroid(.))[, 1]`.
Caused by warning:
! st_centroid assumes attributes are constant over geometries
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 1 remaining warning.

Join all together into the modelling dataset, and just last tidy-up.


# Convert aq_data to sf object
aq_model_data <- st_as_sf(aq_model_data, coords = c("x", "y"), crs = st_crs(mw_100m_cropped))
aq_model_data <- st_transform(aq_model_data, st_crs(mw_100m_cropped))

aq_model_data <- st_join(aq_model_data, mw_100m_grid_sf)

aq_model_data <- aq_model_data %>%
  mutate(x = st_coordinates(st_centroid(.))[, 1],
         y = st_coordinates(st_centroid(.))[, 2]) %>%
  st_drop_geometry() %>%
  mutate(building_coverage_pct = building_coverage_pct/100)

aq_model_data <- aq_model_data %>%
  mutate(building_coverage_pct_z = scale(.$building_coverage_pct)[,1])

Model 1:

“We fitted a spatially smooth regression model for log-transformed PM2.5 concentrations using a Gaussian process (GP) smooth over spatial coordinates (x, y) to capture flexible spatial trends. Seasonal variation was modelled using a Fourier series expansion of day-of-year up to the 3rd harmonic (i.e., sine and cosine terms for annual, semi-annual, and tri-annual cycles) to account for complex seasonal patterns. The model was fitted in a Bayesian framework using brms with a Gaussian likelihood and the cmdstanr backend.”

Note, priors are still causing issues for me, so we will comment out now, and use the defauly stan weakly informative priors

Priors


priors <- c(
  prior(normal(3.4, 1), class = "Intercept"),         # Weakly informative on log_pm2_5
  prior(exponential(1), class = "sdgp"),              # GP standard deviation prior
  #prior(student_t(3, 0, 5.9), class = "sds"),               # Smooth term std dev prior (key!)
  prior(exponential(1), class = "sigma"),             # Observation error
  prior(normal(0,10), class = "b")
)

Fit prior only model

Now model with data.

Compare prior-only model to model with data using priorsense package:


# m1_draws <- as_draws_df(m1)
# 
# # Extract prior and posterior draws
# powerscale_sensitivity(m1, variable = c("b_Intercept", "b_sin_doy", "b_cos_doy", 
#                                         "sdgp_gpxy", "sigma", "Intercept"))
# 
# powerscale_plot_dens(m1, variable = c("b_Intercept", "b_sin_doy", "b_cos_doy", 
#                                         "sdgp_gpxy", "sigma", "Intercept"))

Predictions by space and time. Here, although we only have data within clusters, we will predict for cells outside of clusters based on covariates. We will also predict for the month for whcih we do not have data.

Now just draw 50 random coordinates, and predict by time to see whether we captured the trend.

Model 2: With covariates

Now we include grid level covariates of distance to the road, population density, and building footprint percent, along witht the mean temp and huidity on the day of measurement (from the purple air monitors)

Again, priors to be fixed later

Predictions by space and time

Sample coordinates, and plot over time

Compare models, using LOO CV

loo_compare(loo_m1, loo_m2)
   elpd_diff se_diff
m2    0.0       0.0 
m1 -115.8      18.6 

TODO

LS0tCnRpdGxlOiAiQmxhbnR5cmUgYWlyIHF1YWxpdHkgbW9kZWxsaW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoYnJtcykKbGlicmFyeSh0aWR5YmF5ZXMpCmxpYnJhcnkoc2YpCmxpYnJhcnkobWdjdikKbGlicmFyeShwcmlvcnNlbnNlKQpsaWJyYXJ5KG9zbWRhdGEpCmxpYnJhcnkobm5nZW8pIApgYGAKCgojIyMgQWlyIHF1YWxpdHkgZGF0YQoKQnkgc3VtbWFyeSwgYSByYW5kb20gaG91c2Vob2xkIHN1cnZleSB3YXMgY29uZHVjdGVkIGluIEJsYW50eXJlIE1hbGF3aSBkdXJpbmcgMjAxOS0yMDIwIChwcmUtQ09WSUQgaW4gTWFsYXdpKSBhcyBwYXJ0IG9mIGEgVEIgY2x1c3RlciByYW5kb21pc2VkIHRyaWFsICBwcmUtaW50ZXJ2ZW50aW9uIHByZXZhbGVuY2Ugc3VydmV5IChzdW1hbXJpc2VkIGhlcmU6IGh0dHBzOi8vZXVyb3BlcG1jLm9yZy9hcnRpY2xlL01FRC8zNzg2MjI4NCkuIEZpZWxkd29ya2VycyBjYXJyaWVkIHB1cnBsZSBhaXIgbW9uaXRvcnMgYXR0YWNoZWQgdG8gdGhlaXIgYmFja3BhY2tzLCB3aXRoIG1lYXN1cmVtZW50cyBzZXQgdG8gcmVhZCBldmVyeSA5MCBzZWNvbmRzLiBOb3QgYWxsIGZpZWxkd29ya2VycyBoYWQgYSBtb25pdG9yLiBQcmV2aW91c2x5LCBIZWxlbiBTYXZhZ2UgY2xlYW5lZCB0aGVzZSBtb25pdG9yIGRhdGEsIGFuZCBtZXJnZWQgdG8gaG91c2Vob2xkIHF1ZXN0aW9ubmFpcmUgZGF0YSwgZmlsdGVyaW5nIG1lYXN1cmVtZW50cyBieSBpbnRlcnZpZXcgdGltZXMuIFRoZXJlZm9yZSwgbWVhc3VyZW1lbnRzIGFyZSBpbmRvb3IgaG91c2Vob2xkIG1lYXN1cmVtZW50cy4KCkNsdXN0ZXIgYm91bmRhcmllcyAoNzIgaW4gdG90YWwpIGFyZSBiYXNlZCBvbiBNaW5pc3RyeSBvZiBIZWFsdGggQ29tbXVuaXR5IEhlYWx0aCBXb3JrZXIgY2F0Y2htZW50IGFyZWFzLCByZWZpbmVkIGluIGNvbGxhYm9yYXRpb24gd2l0aCByZXNlYXJjaGVycy4gVGhlc2Ugd2VyZSB0aGUgdW5pdCBvZiByYW5kb21pc2F0aW9uIGZvciB0aGUgU0NBTEUgY2x1c3RlciByYW5kb21pc2VkIHRyaWFsLgoKQWxsIGFpciBxdWFsaXR5IG1lYXN1cmVtZW50cyB3ZXJlIHRoZW4gdGFrZW4gZnJvbSBob3VzZWhvbGRzIHdpdGhpbiB0aGUgNzIgU0NBTEUgY2x1c3Rlci4KCmBgYHtyfQpsb2FkKCJpbnB1dF9kYXRhL2FxX2luLlJEYXRhIikgI2NsZWFuZWQgYWlyLXF1YWxpdHkgZGF0YXNldApsb2FkKCJpbnB1dF9kYXRhL3NjYWxlXzcyX2NsdXN0ZXJzLnJkYSIpICNTQ0FMRSBjbHVzdGVycwpgYGAKCkdldCBkYXRhIGludG8gY29ycmVjdCBzaGFwZSBhbmQgYWdncmVnYXRlIG1lYXN1cmVtZW50cyBwZXIgaG91c2Vob2xkLiBOb3RlIGFzIHB1cnBsZSBhaXIgZGV2aWNlcyB0b29rIG1lYXN1cmVtZW50cyBldmVyeSA5MCBzZWNvbmRzLCBtb3N0bHkgaG91c2hvbGRzIHN1cnZleWVkIGhhdmUgbXVsdGlwbGUgbWVhc3VyZW1lbnRzLiBIZXJlLCBmb3IgY29udmVuaWVuY2UsIHdlIHRha2UgdGhlIG1lYW4gb2YgdGhlc2UgbWVhc3VyZW1lbnQgcGVyIGhvdXNlaG9sZC4KCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CmFxX2RhdCA8LSBhcV9pbiAlPiUKICBzZWxlY3QoZGF0ZXRpbWUsIGgwMmNsX2lkLCBoaF9pZCwgaGhfbGF0LCBoaF9sb24sIHRlbXBfYywgY3VycmVudF9odW1pZGl0eSwgbWVhbl9wbV8yXzUsIGRpc3RhbmNlX2ttKSAlPiUKIG11dGF0ZSgKICAgZGF0ZXRpbWUgPSB5bWRfaG1zKGRhdGV0aW1lKSwKICAgaG91ciA9IGhvdXIoZGF0ZXRpbWUpICsgbWludXRlKGRhdGV0aW1lKS82MCwKICAgZG95ID0geWRheShkYXRldGltZSksCiAgIHggPSBoaF9sb24sCiAgIHkgPSBoaF9sYXQpICU+JQogIGdyb3VwX2J5KGhoX2lkKSAlPiUKICByZWZyYW1lKGgwMmNsX2lkID0gaDAyY2xfaWQsCiAgICAgICAgICB4ID0geCwKICAgICAgICAgIHkgPSB5LAogICAgICAgICAgbWVhbl9kb3kgPSBtZWFuKGRveSwgbmEucm09VFJVRSksCiAgICAgICAgICBtZWFuX3BtMl81ID0gbWVhbihtZWFuX3BtXzJfNSksIAogICAgICAgICAgbWVhbl90ZW1wX2MgPSBtZWFuKHRlbXBfYywgbmEucm09VFJVRSksCiAgICAgICAgICBtZWFuX2N1cnJlbnRfaHVtaWRpdHkgPSBtZWFuKGN1cnJlbnRfaHVtaWRpdHksIG5hLnJtPVRSVUUpKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIG11dGF0ZShsb2dfcG0yXzUgPSBsb2cobWVhbl9wbTJfNSkpCgoKI3dlIHdpbGwgdXNlIEZvdXJpZXIgc2VyaWVzIGNvbXBvbmVudHMgd2l0aCBtdWx0aXBsZSBoYXJtb25pY3MgdG8gbW9kZWwgZGF5LW9mLXRoZSB5ZWFyIGVmZmVjdHMKYXFfZGF0IDwtIGFxX2RhdCAlPiUKICBtdXRhdGUoCiAgICBzaW5fZG95MSA9IHNpbigyICogcGkgKiBtZWFuX2RveSAvIDM2NSksCiAgICBjb3NfZG95MSA9IGNvcygyICogcGkgKiBtZWFuX2RveSAvIDM2NSksCiAgICBzaW5fZG95MiA9IHNpbig0ICogcGkgKiBtZWFuX2RveSAvIDM2NSksCiAgICBjb3NfZG95MiA9IGNvcyg0ICogcGkgKiBtZWFuX2RveSAvIDM2NSksCiAgICBzaW5fZG95MyA9IHNpbig2ICogcGkgKiBtZWFuX2RveSAvIDM2NSksCiAgICBjb3NfZG95MyA9IGNvcyg2ICogcGkgKiBtZWFuX2RveSAvIDM2NSkKICApCgojY2hlY2sgc29tZSB2YXJpYWJsZXMKYXFfZGF0ICU+JQogIHNlbGVjdChoaF9pZCwgbG9nX3BtMl81LCBtZWFuX3RlbXBfYywgbWVhbl9jdXJyZW50X2h1bWlkaXR5LCBtZWFuX2RveSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGxvZ19wbTJfNSwgbWVhbl90ZW1wX2MsIG1lYW5fY3VycmVudF9odW1pZGl0eSwgbWVhbl9kb3kpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9dmFsdWUsIGZpbGw9bmFtZSkpICsKICBmYWNldF93cmFwKG5hbWV+Liwgc2NhbGVzID0gImZyZWVfeCIpCgojUE0yLjUgZGlzdHJpYnV0aW9uIGJ5IGRheSBvZiB0aGUgeWVhcgphcV9kYXQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21faml0dGVyKGFlcyh4ID0gbWVhbl9kb3ksIHk9bG9nX3BtMl81KSwgY29sb3VyPSJkYXJrcmVkIiwgYWxwaGE9MC41KSArCiAgdGhlbWVfZ2dkaXN0KCkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyPSJncmV5NzgiKSkKI05vdGUgdGhhdCB0aGVyZSB3YXMgbm8gZGF0YSBjb2xsZWN0aW9uIGluIEFwcmlsIG9mIGVpdGhlciB5ZWFyCgoKI3Bsb3QgdGhlIG1lYXN1cmVtZW50cyBvbiBhIG1hcAphcV9kYXQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YT1zY2FsZV83Ml9jbHVzdGVycywgZmlsbD1OQSkgKwogIGdlb21fcG9pbnQoYWVzKHg9eCwgeT15LCBjb2xvdXI9bG9nX3BtMl81KSwgc2l6ZT0wLjEpKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYygpICsKICB0aGVtZV9nZ2Rpc3QoKSArCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXI9ImdyZXk3OCIpKSAKCiNOb3RlIHRoZSB3YXJuaW5nIGFib3V0IG9sZCBjb29yZGluYXRlIHJlZmVyZW5jZSBzeXN0ZW0gLSB3ZSB3aWxsIGZpeCB0aGlzIGJlbG93LgoKYGBgCgojIyMgQ292YXJpYXRlcwoKUG9wdWxhdGlvbiBjb3VudHMgYW5kIGRlbnNpdHkKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CgojcmVhZCBpbiB0aGUgLnRpZmYgaW1hZ2Ugb2YgcG9wdWxhdGlvbiBjb3VudCBmcm9tIFdvcmxkcG9wCiNodHRwczovL2h1Yi53b3JsZHBvcC5vcmcvZ2VvZGF0YS9zdW1tYXJ5P2lkPTE1NjAKbXdfMTAwbSA8LSBzdGFyczo6cmVhZF9zdGFycygiaW5wdXRfZGF0YS9td2lfcHBwXzIwMjAudGlmIikKCgojZGVmaW5lIGJ1ZmZlciBhcm91bmQKYnVmZmVyX20gPC0gNTAwCgojYXBwcm94aW1hdGUgY29udmVyc2lvbiBmYWN0b3IgKGRlZ3JlZXMgcGVyIG1ldGVyKQojYWRqdXN0IGZvciBsYXRpdHVkZSBmb3IgbG9uZ2l0dWRlIGRpcmVjdGlvbgpsYXRfbWVhbiA8LSBtZWFuKGFxX2RhdCR5KQpkZWdfcGVyX21fbGF0IDwtIDEgLyAxMTEzMjAgICMgUm91Z2ggY29udmVyc2lvbiBmb3IgbGF0aXR1ZGUKZGVnX3Blcl9tX2xvbiA8LSAxIC8gKDExMTMyMCAqIGNvc3BpKGxhdF9tZWFuIC8gMTgwKSkgICMgQWRqdXN0IGZvciBsYXRpdHVkZQoKI2V4cGFuZGJvdW5kaW5nIGJveCB3aXRoIGJ1ZmZlcgpiYm94X2J1ZmZlcmVkIDwtIHN0X2Jib3goYygKICB4bWluID0gbWluKGFxX2RhdCR4KSAtIGJ1ZmZlcl9tICogZGVnX3Blcl9tX2xvbiwKICB4bWF4ID0gbWF4KGFxX2RhdCR4KSArIGJ1ZmZlcl9tICogZGVnX3Blcl9tX2xvbiwKICB5bWluID0gbWluKGFxX2RhdCR5KSAtIGJ1ZmZlcl9tICogZGVnX3Blcl9tX2xhdCwKICB5bWF4ID0gbWF4KGFxX2RhdCR5KSArIGJ1ZmZlcl9tICogZGVnX3Blcl9tX2xhdAopLCBjcnMgPSBzdF9jcnMobXdfMTAwbSkpCgojY3JvcCB3b3JsZHBvcCByYXN0ZXIgdG8gYnVmZmVyZWQgYmJveAptd18xMDBtX2Nyb3BwZWQgPC0gc3RfY3JvcChtd18xMDBtLCBiYm94X2J1ZmZlcmVkKQoKI3Bsb3QKcGxvdChtd18xMDBtX2Nyb3BwZWQpCgoKI3RoZXJlIGFyZSBhIHNtYWxsIG51bWJlciBvZiBjZWxscyBpbiB0aGUgY2VudHJlIHRoYXQgYXJlIE5BCiNJIHRoaW5rIHRoZXNlIGFyZSB0aGUgbWlsaXRhcnkgcmFkYXIgb24gTW91bnQgU29jaGUsCiNzbyBubyBleHBlY3RlZCBwb3B1bGF0aW9uCiNyZXBsYWNlIHdpdGggMAptd18xMDBtX2Nyb3BwZWRbWzFdXVtpcy5uYShtd18xMDBtX2Nyb3BwZWRbWzFdXSldIDwtIDAKCiNkaWQgaXQgd29yaz8KcGxvdChtd18xMDBtX2Nyb3BwZWQpCgojeG9udmVydCB0byBzZiBvYmplY3QKYXFfc2YgPC0gc3RfYXNfc2YoYXFfZGF0LCBjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gc3RfY3JzKG13XzEwMG1fY3JvcHBlZCkpCgojbWVyZ2Ugd2l0aCB0aGUgcG9wdWxhdGlvbiBjb3VudCBkYXRhCmFxX3NmJHBvcF9kZW5zaXR5IDwtIHN0YXJzOjpzdF9leHRyYWN0KG13XzEwMG1fY3JvcHBlZCwgYXFfc2YpW1sxXV0KCiNnZXQgcG9wdWxhdGlvbiBkZW5zaXR5CmFxX21vZGVsX2RhdGEgPC0gYXFfc2YgJT4lCiAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQogIGFzX3RpYmJsZSgpICU+JQogIG11dGF0ZShwb3BfZGVuc2l0eV9rbTIgPSBwb3BfZGVuc2l0eSAvIDAuMDEpICU+JQogIGxlZnRfam9pbihhcV9kYXQgJT4lIHNlbGVjdChoaF9pZCwgeCwgeSkpCgojZml4IHRoZSBjb29yZGluYXRlIGNycyBvZiB0aGUgc2NhbGUgY2x1c3RlcnMKc2NhbGVfNzJfY2x1c3RlcnMgPC0gIHN0X3RyYW5zZm9ybShzY2FsZV83Ml9jbHVzdGVycywgc3RfY3JzKG13XzEwMG0pKQoKYGBgCgpCdWlsZGluZyBkZW5zaXR5IChpLmUuIHdlIGdldCB0aGUgYnVpbGRpbmcgZm9vdHByaW50cywgYW5kIGNhbGN1bGF0ZSB0aGVpciBjb21iaW5lZCBmb290cHJpbnQgYXJlYSBwZXIgZ3JpZCBjZWxsLCB0aGVuIGNhbGN1bGF0ZSB3aGF0IHBlcmNlbnRhZ2Ugb2YgdGhlIGdyaWQgY2VsbCBpcyAiYnVpbGRpbmcgZm9vdHByaW50IikKaHR0cHM6Ly9zaXRlcy5yZXNlYXJjaC5nb29nbGUvZ3Ivb3Blbi1idWlsZGluZ3MvI29wZW4tYnVpbGRpbmdzLWRvd25sb2FkIAoKVXNpbmcgVmVyc2lvbiAyIGhlcmUgLSBjYW4gdXBkYXRlIGxhdGVyIHRvIFYzLCB3aXRoIGJldHRlciBwcmVjaXNpb24sIGFuZCB5ZWFyLXNwZWNpZmljIGRhdGEuIChJIHRoaW5rIHRoaXMgaXMgZm9yIDIwMjAgY3VycmVudGx5KQoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KCiNyZWFkIGluIHRoZSBkYXRhIHNldAojaXMgYSBzdGFycyBkYXRhc2V0CmJ1aWxkaW5ncyA8LSByZWFkX3JkcygiaW5wdXRfZGF0YS9ibGFudHlyZV9idWZmX2J1aWxkaW5ncy5yZHMiKQoKI21hdGNoIHRoZSBjcnMgdG8gdGhlIHBvcHVsYXRpb24gZGF0YQpidWlsZGluZ3MgPC0gIHN0X3RyYW5zZm9ybShidWlsZGluZ3MsIHN0X2Nycyhtd18xMDBtKSkKCiNjb252ZXJ0IHN0YXJzIG9iamVjdCB0byBwb2x5Z29ucwptd18xMDBtX2dyaWRfc2YgPC0gc3RfYXNfc2YobXdfMTAwbV9jcm9wcGVkLCBhc19wb2ludHMgPSBGQUxTRSwgbWVyZ2UgPSBGQUxTRSkKCiNhZGQgZ3JpZCBjZWxsIElEIGZvciBncm91cGluZwptd18xMDBtX2dyaWRfc2YgPC0gbXdfMTAwbV9ncmlkX3NmICU+JQogIG11dGF0ZShncmlkX2lkID0gcm93X251bWJlcigpKQoKI2pvaW4gYnVpbGRpbmcgZm9vdHByaW50IGRhdGEgdG8gdGhlIHBvcHVsYXRpb24gZGF0YQpidWlsZGluZ3Nfd2l0aF9ncmlkIDwtIHN0X2pvaW4oYnVpbGRpbmdzLCBtd18xMDBtX2dyaWRfc2YsIGxlZnQgPSBGQUxTRSkKCiNmaWx0ZXIgYnkgY29uZmlkZW5jZSBvZiBidWlsZGluZyBmb290cHJpbnQsIGFuZCBieSBmb290cHJpbnQgc2l6ZQojaW4gSGFubmFoIFIncyBwcmV2aW91cyBleHBlcmllbWVudHMsIHRoaXMgd2FzIGEgZ29vZCBjb21wcm9taXNlCiNhbmQgbWF0Y2hlcyB3ZWxsIHdpdGggaG9tZSB2aXNpdHMgb24gdGhlIGdyb3VuZC4KYnVpbGRpbmdzX3dpdGhfZ3JpZCA8LSBidWlsZGluZ3Nfd2l0aF9ncmlkICU+JQogIGZpbHRlcihhcmVhX2luX21ldGVycz4yMCkgJT4lCiAgZmlsdGVyKGFyZWFfaW5fbWV0ZXJzPDMwMCkgJT4lCiAgZmlsdGVyKGNvbmZpZGVuY2U+MC42OSkKCiNzdW0gYnVpbGRpbmcgZm9vdHByaW50IHBlciBncmlkIGNlbGwKYnVpbGRpbmdfYXJlYV9wZXJfY2VsbCA8LSBidWlsZGluZ3Nfd2l0aF9ncmlkICU+JQogIGdyb3VwX2J5KGdyaWRfaWQpICU+JQogIHN1bW1hcmlzZSh0b3RhbF9idWlsZGluZ19hcmVhX20yID0gc3VtKGFyZWFfaW5fbWV0ZXJzLCBuYS5ybSA9IFRSVUUpKQoKI2NlbGwgYXJlYSBpbiBtIHNxdWFyZWQKY2VsbF9hcmVhX20yIDwtIDEwMCAqIDEwMAoKI2NvbXB1dGUgcGVyY2VudGFnZSBjb3ZlcmFnZQpidWlsZGluZ19hcmVhX3Blcl9jZWxsIDwtIGJ1aWxkaW5nX2FyZWFfcGVyX2NlbGwgJT4lCiAgbXV0YXRlKGJ1aWxkaW5nX2NvdmVyYWdlX3BjdCA9ICh0b3RhbF9idWlsZGluZ19hcmVhX20yIC8gY2VsbF9hcmVhX20yKSAqIDEwMCkKCiNqb2luCm13XzEwMG1fZ3JpZF9zZiA8LSBtd18xMDBtX2dyaWRfc2YgJT4lCiAgbGVmdF9qb2luKGJ1aWxkaW5nX2FyZWFfcGVyX2NlbGwgJT4lIHN0X2Ryb3BfZ2VvbWV0cnkoKSwgYnkgPSAiZ3JpZF9pZCIpICU+JQogIG11dGF0ZShidWlsZGluZ19jb3ZlcmFnZV9wY3QgPSByZXBsYWNlX25hKGJ1aWxkaW5nX2NvdmVyYWdlX3BjdCwgMCkpCgojY2hlY2sgYnkgcGxvdHRpbmcKbXdfMTAwbV9ncmlkX3NmICU+JQogIG11dGF0ZSh4ID0gc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQoLikpWywgMV0sCiAgICAgICAgIHkgPSBzdF9jb29yZGluYXRlcyhzdF9jZW50cm9pZCguKSlbLCAyXSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fdGlsZShhZXMoeD14LCB5PXksIGZpbGw9YnVpbGRpbmdfY292ZXJhZ2VfcGN0KSkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJjaXZpZGlzIikgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5NzgiKSkKCmBgYAoKRGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgbWFpbiByb2FkLiBJLmUuIGJlY2F1c2Ugd2UgdGhpbmsgdGhhdCBQTTIuNSBleHBvc3VyZSBjYW4gY29tZSBmcm9tIHJvYWQgdmVoaWNsZXMuCgpXZSB1c2UgT3BlbiBTdHJlZXQgTWFwIChPU00pIGRhdGEgdG8gZ2V0IHRoZSBtYWluIHJvYWRzICh0aGVyZSBhcmUgZmV3IG9mIHRoZXNlIGluIEJsYW50eXJlLi4uIGJ1dCBzZWUgdGhlIG1vc3QgdHJhZmZpYykuIExhdGVyIGNvdWxkIGNvbnNpZGVyIGluY2x1ZGluZyBzb21lIHNtYWxsZXIgcm9hZC4uLgoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KCiNnZXQgdGhlIE9TTSBmZWF0dXJlcy4KcSA8LSBvcHEoYmJveCA9IGJib3hfYnVmZmVyZWQpICU+JQogIGFkZF9vc21fZmVhdHVyZShrZXkgPSAnaGlnaHdheScsIAogICAgICAgICAgICAgICAgICB2YWx1ZSA9IGMoJ3ByaW1hcnknLCAnc2Vjb25kYXJ5JywgJ3RlcnRpYXJ5JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHJ1bmsnLCAnbW90b3J3YXknKSkKCiNpbXBvcnQKb3NtX3JvYWRzIDwtIG9zbWRhdGFfc2YocSkKCiMjZ2V0IHJlYWR5LgptYWluX3JvYWRzIDwtIG9zbV9yb2FkcyRvc21fbGluZXMKbWFpbl9yb2FkcyA8LSBzdF90cmFuc2Zvcm0obWFpbl9yb2Fkcywgc3RfY3JzKG13XzEwMG0pKQoKI3Bsb3Qgcm9hZHMKbWFpbl9yb2FkcyAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gc2NhbGVfNzJfY2x1c3RlcnMsIGNvbG91cj0iZGFya3JlZCIpICsKICBnZW9tX3NmKCkgCgojY3JvcCB0byBncmlkCm1haW5fcm9hZHNfY3JvcHBlZCA8LSBzdF9jcm9wKG1haW5fcm9hZHMsIGJib3hfYnVmZmVyZWQpCgojcGxvdCBhZ2Fpbi4KbWFpbl9yb2Fkc19jcm9wcGVkICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBzY2FsZV83Ml9jbHVzdGVycywgY29sb3VyPSJkYXJrcmVkIikgKwogIGdlb21fc2YoKSAKCiNnZXQgY2VudHJvaWRzIG9mIGdyaWQgY2VsbHMKZ3JpZF9jZW50cm9pZHMgPC0gc3RfY2VudHJvaWQobXdfMTAwbV9ncmlkX3NmKQoKI3VzZSBuZWFyZXN0IG5laWdoYm91ciBzZWFyY2ggdG8gZ2V0IHRoZSBkaXN0YW5jZSBmcm9tIHRoZSBncmlkIGNlbGwgY2VudHJvaWQgdG8gdGhlIG5lYXJlc3QgbWFpbiByb2FkLgpuZWFyZXN0X3JvYWRzIDwtIHN0X25uKGdyaWRfY2VudHJvaWRzLCBtYWluX3JvYWRzX2Nyb3BwZWQsIGsgPSAxLCByZXR1cm5EaXN0ID0gVFJVRSkKZGlzdF90b19yb2FkX20gPC0gc2FwcGx5KG5lYXJlc3Rfcm9hZHMkZGlzdCwgYFtgLCAxKQoKI3NhbWUgYXMgYmVmb3JlOiBhZGQgdG8gZ3JpZAptd18xMDBtX2dyaWRfc2YkZGlzdF90b19yb2FkX20gPC0gZGlzdF90b19yb2FkX20KCiNjaGVjayBwbG90Cm13XzEwMG1fZ3JpZF9zZiAlPiUKICBtdXRhdGUoeCA9IHN0X2Nvb3JkaW5hdGVzKHN0X2NlbnRyb2lkKC4pKVssIDFdLAogICAgICAgICB5ID0gc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQoLikpWywgMl0pICU+JQogIGdncGxvdCgpICsKICBnZW9tX3RpbGUoYWVzKHg9eCwgeT15LCBmaWxsPWRpc3RfdG9fcm9hZF9tKSkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJHIiwgZGlyZWN0aW9uID0gLTEpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5NzgiKSkgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5NzgiKSkKCgoKYGBgCgoKSm9pbiBhbGwgdG9nZXRoZXIgaW50byB0aGUgbW9kZWxsaW5nIGRhdGFzZXQsIGFuZCBqdXN0IGxhc3QgdGlkeS11cC4KCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CgphcV9tb2RlbF9kYXRhIDwtIHN0X2FzX3NmKGFxX21vZGVsX2RhdGEsIGNvb3JkcyA9IGMoIngiLCAieSIpLCBjcnMgPSBzdF9jcnMobXdfMTAwbSkpCgphcV9tb2RlbF9kYXRhIDwtIHN0X2pvaW4oYXFfbW9kZWxfZGF0YSwgbXdfMTAwbV9ncmlkX3NmKQoKYXFfbW9kZWxfZGF0YSA8LSBhcV9tb2RlbF9kYXRhICU+JQogIG11dGF0ZSh4ID0gc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQoLikpWywgMV0sCiAgICAgICAgIHkgPSBzdF9jb29yZGluYXRlcyhzdF9jZW50cm9pZCguKSlbLCAyXSkgJT4lCiAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQogIG11dGF0ZShidWlsZGluZ19jb3ZlcmFnZV9wY3QgPSBidWlsZGluZ19jb3ZlcmFnZV9wY3QvMTAwKQoKYGBgCgoKIyMjIE1vZGVsIDE6CgoKIldlIGZpdHRlZCBhIHNwYXRpYWxseSBzbW9vdGggcmVncmVzc2lvbiBtb2RlbCBmb3IgbG9nLXRyYW5zZm9ybWVkIFBNMi41IGNvbmNlbnRyYXRpb25zIHVzaW5nIGEgR2F1c3NpYW4gcHJvY2VzcyAoR1ApIHNtb290aCBvdmVyIHNwYXRpYWwgY29vcmRpbmF0ZXMgKHgsIHkpIHRvIGNhcHR1cmUgZmxleGlibGUgc3BhdGlhbCB0cmVuZHMuIFNlYXNvbmFsIHZhcmlhdGlvbiB3YXMgbW9kZWxsZWQgdXNpbmcgYSBGb3VyaWVyIHNlcmllcyBleHBhbnNpb24gb2YgZGF5LW9mLXllYXIgdXAgdG8gdGhlIDNyZCBoYXJtb25pYyAoaS5lLiwgc2luZSBhbmQgY29zaW5lIHRlcm1zIGZvciBhbm51YWwsIHNlbWktYW5udWFsLCBhbmQgdHJpLWFubnVhbCBjeWNsZXMpIHRvIGFjY291bnQgZm9yIGNvbXBsZXggc2Vhc29uYWwgcGF0dGVybnMuIFRoZSBtb2RlbCB3YXMgZml0dGVkIGluIGEgQmF5ZXNpYW4gZnJhbWV3b3JrIHVzaW5nIGJybXMgd2l0aCBhIEdhdXNzaWFuIGxpa2VsaWhvb2QgYW5kIHRoZSBjbWRzdGFuciBiYWNrZW5kLiIKCk5vdGUsIHByaW9ycyBhcmUgc3RpbGwgY2F1c2luZyBpc3N1ZXMgZm9yIG1lLCBzbyB3ZSB3aWxsIGNvbW1lbnQgb3V0IG5vdywgYW5kIHVzZSB0aGUgZGVmYXVseSBzdGFuIHdlYWtseSBpbmZvcm1hdGl2ZSBwcmlvcnMKClByaW9ycwoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KIyAKIyBwcmlvcnMgPC0gYygKIyAgIHByaW9yKG5vcm1hbCgwLCAxKSwgY2xhc3MgPSAiSW50ZXJjZXB0IiksCiMgICBwcmlvcihub3JtYWwoMCwxKSwgY2xhc3MgPSAiYiIpLAojICAgcHJpb3Ioc3R1ZGVudF90KDMsIDAsIDIuNSksIGNsYXNzID0gInNpZ21hIiksCiMgICBwcmlvcihleHBvbmVudGlhbCgwLjUpLCBjbGFzcyA9ICJzZGdwIikKIyApCgpgYGAKCkZpdCBwcmlvciBvbmx5IG1vZGVsCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQojIAojIG0xX3ByaW9yIDwtIGJybSgKIyAgICAgZm9ybXVsYSA9IGxvZ19wbTJfNSB+IGdwKHgsIHksIGs9MTUpICsKIyAgICAgICBzaW5fZG95MSArIGNvc19kb3kxICsKIyAgICAgICBzaW5fZG95MiArIGNvc19kb3kyICsKIyAgICAgICBzaW5fZG95MyArIGNvc19kb3kzLAojICAgICBkYXRhID0gYXFfbW9kZWxfZGF0YSwKIyAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwKIyAgICAgcHJpb3IgPSBwcmlvcnMsCiMgICAgIHNhbXBsZV9wcmlvciA9ICJvbmx5IiwKIyAgICAgY2hhaW5zID0gNCwgY29yZXMgPSA0LAojICAgICBiYWNrZW5kID0gImNtZHN0YW5yIgojICAgKQojIAojIAojIHN1bW1hcnkobTFfcHJpb3IpCiMgcGxvdChtMV9wcmlvcikKCmBgYAoKTm93IG1vZGVsIHdpdGggZGF0YS4KCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQptMSA8LSBicm0oCiAgICBmb3JtdWxhID0gbG9nX3BtMl81IH4gZ3AoeCwgeSwgaz0xNSkgICsKICAgIHNpbl9kb3kxICsgY29zX2RveTEgKwogICAgc2luX2RveTIgKyBjb3NfZG95MiArCiAgICBzaW5fZG95MyArIGNvc19kb3kzLAogICAgZGF0YSA9IGFxX21vZGVsX2RhdGEsCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpLAogICAgI3ByaW9yID0gcHJpb3JzLAogICAgY2hhaW5zID0gNCwgY29yZXMgPSA0LAogICAgYmFja2VuZCA9ICJjbWRzdGFuciIKICApCgpzdW1tYXJ5KG0xKQpjb25kaXRpb25hbF9lZmZlY3RzKG0xKQpwcF9jaGVjayhtMSkKcGxvdChtMSkKCmBgYAoKQ29tcGFyZSBwcmlvci1vbmx5IG1vZGVsIHRvIG1vZGVsIHdpdGggZGF0YSB1c2luZyBgcHJpb3JzZW5zZWAgcGFja2FnZToKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CgojIG0xX2RyYXdzIDwtIGFzX2RyYXdzX2RmKG0xKQojIAojICMgRXh0cmFjdCBwcmlvciBhbmQgcG9zdGVyaW9yIGRyYXdzCiMgcG93ZXJzY2FsZV9zZW5zaXRpdml0eShtMSwgdmFyaWFibGUgPSBjKCJiX0ludGVyY2VwdCIsICJiX3Npbl9kb3kiLCAiYl9jb3NfZG95IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzZGdwX2dweHkiLCAic2lnbWEiLCAiSW50ZXJjZXB0IikpCiMgCiMgcG93ZXJzY2FsZV9wbG90X2RlbnMobTEsIHZhcmlhYmxlID0gYygiYl9JbnRlcmNlcHQiLCAiYl9zaW5fZG95IiwgImJfY29zX2RveSIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2RncF9ncHh5IiwgInNpZ21hIiwgIkludGVyY2VwdCIpKQpgYGAKClByZWRpY3Rpb25zIGJ5IHNwYWNlIGFuZCB0aW1lLiBIZXJlLCBhbHRob3VnaCB3ZSBvbmx5IGhhdmUgZGF0YSB3aXRoaW4gY2x1c3RlcnMsIHdlIHdpbGwgcHJlZGljdCBmb3IgY2VsbHMgb3V0c2lkZSBvZiBjbHVzdGVycyBiYXNlZCBvbiBjb3ZhcmlhdGVzLgpXZSB3aWxsIGFsc28gcHJlZGljdCBmb3IgdGhlIG1vbnRoIGZvciB3aGNpaCB3ZSBkbyBub3QgaGF2ZSBkYXRhLgoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KCiNzZXRfdXAgcHJlZGljdGlvbiBkYXRlIGZyYW1lCm5kX20xIDwtIHN0X2FzX3NmKG13XzEwMG1fY3JvcHBlZCkgICU+JQogIG11dGF0ZShjZW50cm9pZCA9IHN0X2NlbnRyb2lkKGdlb21ldHJ5KSkgJT4lCiAgbXV0YXRlKHggPSBzdF9jb29yZGluYXRlcyhjZW50cm9pZClbLCAxXSwKICAgICAgICAgeSA9IHN0X2Nvb3JkaW5hdGVzKGNlbnRyb2lkKVssIDJdKSAlPiUKICBzZWxlY3QoLWNlbnRyb2lkKSAgJT4lCiAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQogIHJlbmFtZShwb3BfZGVuc2l0eSA9IDEpICU+JQogIG11dGF0ZShwb3BfZGVuc2l0eV9rbTIgPSBwb3BfZGVuc2l0eSAvIDAuMDEpCgojZ2V0IHRoZSBmaXJzdCBkYXkgb2YgZWFjaCBtb250aCBmb3IgcHJlZGljdGlvbgpmaXJzdF9kYXlzIDwtIHltZChwYXN0ZTAoIjIwMjAtIiwgc3ByaW50ZigiJTAyZCIsIDE6MTIpLCAiLTAxIikpCmZpcnN0X2RheV9kb3kgPC0geWRheShmaXJzdF9kYXlzKQoKI2NhbGN1bGF0ZSBGb3VyaWVyIHRlcm1zCmZpcnN0X2RheV9zZWFzb25hbGl0eSA8LSB0aWJibGUoCiAgbWVhbl9kb3kgPSBmaXJzdF9kYXlfZG95LAogIHNpbl9kb3kxID0gc2luKDIgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBjb3NfZG95MSA9IGNvcygyICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgc2luX2RveTIgPSBzaW4oNCAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIGNvc19kb3kyID0gY29zKDQgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBzaW5fZG95MyA9IHNpbig2ICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgY29zX2RveTMgPSBjb3MoNiAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIGRhdGUgPSBmaXJzdF9kYXlzCikKCiNleHBhbmQgZ3JpZCBmb3IgcHJlZGljdGlvbgpuZF9tMSA8LSBuZF9tMSAlPiUKICBjcm9zc2luZyhmaXJzdF9kYXlfc2Vhc29uYWxpdHkpCgojdGFrZSBwb3N0ZXJpb3IgZHJhd3MgLSBub3RlIHN0b3JpbmcgYXMgYW4gcnZhcnMgb2JqZWN0IGZvciBlZmZpY2llbmN5CiNub3RlIGNhbiBvbmx5IG1hbmFnZSB0aGlzIHdpdGhvdXQgY3Jhc2hpbmcgY29tcHV0ZXIhCiN0byBhZGRyZXNzIGxhdGVyLCBhbmQgaW1wcm92ZSBlZmZpY2llbnkgZm9yIG1vcmUgZHJhd3MKbTFfZHJhd3MgPC0gYWRkX2VwcmVkX3J2YXJzKG9iamVjdCA9IG0xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IG5kX20xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmRyYXdzID0gMjAwKSAKCiNub3cgZXh0cmFjdCB0aGUgc3VtbWFyeSBtZWFuIGFuZCBzZCBmb3IgZWFjaCBtb250aC1ncmlkIGNlbGwgY29tYmluYXRpb24KbTFfZXByZWRfYXJyYXkgPC0gcG9zdGVyaW9yOjpkcmF3c19vZihtMV9kcmF3cyQuZXByZWQpCgojY29tcHV0ZSBwb3N0ZXJpb3IgbWVhbnMgcGVyIGxvY2F0aW9uCm0xX2RyYXdzJC5lcHJlZF9tZWFuIDwtIGNvbE1lYW5zKG0xX2VwcmVkX2FycmF5KQoKI2NvbXB1dGUgcG9zdGVyaW9yIHNkcyBwZXIgbG9jYXRpb24KbTFfZHJhd3MkLmVwcmVkX3NkIDwtIGFwcGx5KG0xX2VwcmVkX2FycmF5LCAyLCBzZCkKCm0xX3N1bSA8LSBtMV9kcmF3cyAlPiUgCiAgc2VsZWN0KGdyaWRfaWQsIHgsIHksIGRhdGUsIG1vbnRoLCAuZXByZWRfbWVhbiwgLmVwcmVkX3NkKQoKCiNwbG90IHByZWRpY3Rpb25zCm0xX3N1bSAlPiUgIAogIG11dGF0ZShkYXRlID0gbW9udGgoZGF0ZSwgbGFiZWw9VFJVRSkpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3RpbGUoYWVzKHggPSB4LCB5PXksIGZpbGw9LmVwcmVkX2xvZ19wbTIuNSkpICsKICBnZW9tX3NmKGRhdGEgPSBzY2FsZV83Ml9jbHVzdGVycywgY29sb3VyPSJncmV5NzgiLCBmaWxsPU5BKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArCiAgZmFjZXRfd3JhcChkYXRlfi4pICsKICBsYWJzKHRpdGxlID0gIkxvZyhQTTIuNSkgZXhwb3N1cmUiLAogICAgICAgeD0iIiwKICAgICAgIHk9IiIpICsKICB0aGVtZV9nZ2Rpc3QoKSArCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPU5BLCBjb2xvdXI9ImdyZXk3OCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXk3OCIpKQoKYGBgCgpOb3cganVzdCBkcmF3IDUwIHJhbmRvbSBjb29yZGluYXRlcywgYW5kIHByZWRpY3QgYnkgdGltZSB0byBzZWUgd2hldGhlciB3ZSBjYXB0dXJlZCB0aGUgdHJlbmQuCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQojc2FtcGxlIGNvb3JkaW5hdGUgcG9pbnRzIGZyb20gdGhlIGhvdXNlaG9sZCBkYXRhc2V0CiN3ZSB3aWxsIGZpeCB0aGUgc21hbGwgbnVtYmVyIHNhbXBsZWQgbGF0ZXIhCnNldC5zZWVkKDEyMykgCnNhbXBsZWRfcG9pbnRzX20xIDwtIGFxX21vZGVsX2RhdGEgJT4lCiAgc2FtcGxlX24oNTApICU+JQogIHNlbGVjdCh4LCB5KQoKI2dlbmVyYXRlIERPWSAw4oCTMzY1IGFuZCBjYWxjdWxhdGUgRm91cmllciB0ZXJtcwpkb3lfZ3JpZCA8LSB0aWJibGUoZG95ID0gMDozNjUpICU+JQogIG11dGF0ZSgKICAgIHNpbl9kb3kxID0gc2luKDIgKiBwaSAqIGRveSAvIDM2NSksCiAgICBjb3NfZG95MSA9IGNvcygyICogcGkgKiBkb3kgLyAzNjUpLAogICAgc2luX2RveTIgPSBzaW4oNCAqIHBpICogZG95IC8gMzY1KSwKICAgIGNvc19kb3kyID0gY29zKDQgKiBwaSAqIGRveSAvIDM2NSksCiAgICBzaW5fZG95MyA9IHNpbig2ICogcGkgKiBkb3kgLyAzNjUpLAogICAgY29zX2RveTMgPSBjb3MoNiAqIHBpICogZG95IC8gMzY1KQogICkKCiNleHBhbmQgZ3JpZCBhY3Jvc3Mgc2FtcGxlZCBsb2NhdGlvbnMKcHJlZGljdGlvbl9kZl9tMSA8LSBzYW1wbGVkX3BvaW50c19tMSAlPiUKICBjcm9zc2luZyhkb3lfZ3JpZCkKCiNhZGQgcHJlZGljdGlvbnMKcHJlZHNfbTEgPC0gYWRkX2VwcmVkX2RyYXdzKG9iamVjdCA9IG0xLCBuZXdkYXRhID0gcHJlZGljdGlvbl9kZl9tMSkKCiNzdW1tYXJpc2UKcHJlZHNfbTFfc3VtIDwtIHByZWRzX20xICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShkb3kpICU+JQogIHN1bW1hcmlzZSguZXByZWRfbWVhbiA9IG1lYW4oLmVwcmVkKSwKICAgICAgICAgICAgLmxvd2VyID0gcXVhbnRpbGUoLmVwcmVkLCBwcm9icz0wLjAyNSksCiAgICAgICAgICAgIC51cHBlciA9IHF1YW50aWxlKC5lcHJlZCwgcHJvYnMgPSAwLjk3NSkpCgojR0V0IHRoZSBvYnNlcnZlZCBkYXRhCm9ic2VydmVkX2RhdGEgPC0gYXFfbW9kZWxfZGF0YSAlPiUKICBzZWxlY3QobWVhbl9kb3ksIGxvZ19wbTJfNSkgCgojcGxvdApwcmVkc19tMV9zdW0gJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcmliYm9uKGFlcyh4PWRveSwgeW1pbj0ubG93ZXIsIHltYXggPSAudXBwZXIpLCBmaWxsPSJzdGVlbGJsdWUiLCBhbHBoYT0wLjMpICsKICBnZW9tX2xpbmUoYWVzKHg9ZG95LCB5PS5lcHJlZF9tZWFuKSkgKwogIGdlb21faml0dGVyKGRhdGEgPSBvYnNlcnZlZF9kYXRhLCBhZXMoeCA9IG1lYW5fZG95LCB5ID0gbG9nX3BtMl81KSwKICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgYWxwaGEgPSAwLjYsIHdpZHRoID0gMC41LCBoZWlnaHQgPSAwLjAsIHNpemUgPSAxLjIpICsKICBsYWJzKHRpdGxlID0gIk1vZGVsLWVzdGltYXRlZCBsb2coUE0yLjUpIHdpdGggZW1waXJpY2FsIG1lYXN1cmVtZW50cyIsCiAgICAgICBzdWJ0aXRsZSA9ICJNb2RlbCBwcmVkaWN0aW9ucyB3aXRoIDk1JSBDckkgYW5kIG9ic2VydmVkIGRhdGEgcG9pbnRzIiwKICAgICAgIHggPSAiRGF5IG9mIHllYXIiLAogICAgICAgeSA9ICJsb2coUE0yLjUpIiwKICAgICAgIGNhcHRpb24gPSAiTW9kZWxsZWQgZXN0aW1hdGVzIHJlc3RyaWN0ZWQgdG8gd2l0aGluIGNsdXN0ZXJzIikgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5NzgiKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpgYGAKCiMjIyBNb2RlbCAyOiBXaXRoIGNvdmFyaWF0ZXMKCk5vdyB3ZSBpbmNsdWRlIGdyaWQgbGV2ZWwgY292YXJpYXRlcyBvZiBkaXN0YW5jZSB0byB0aGUgcm9hZCwgcG9wdWxhdGlvbiBkZW5zaXR5LCBhbmQgYnVpbGRpbmcgZm9vdHByaW50IHBlcmNlbnQsIGFsb25nIHdpdGh0IHRoZSBtZWFuIHRlbXAgYW5kIGh1aWRpdHkgb24gdGhlIGRheSBvZiBtZWFzdXJlbWVudCAoZnJvbSB0aGUgcHVycGxlIGFpciBtb25pdG9ycykKCkFnYWluLCBwcmlvcnMgdG8gYmUgZml4ZWQgbGF0ZXIKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CiMgcHJpb3JzIDwtIGMoCiMgICBwcmlvcihub3JtYWwoMCwgMSksIGNsYXNzID0gIkludGVyY2VwdCIpLAojICAgcHJpb3Iobm9ybWFsKDAsMSksIGNsYXNzID0gImIiKSwKIyAgIHByaW9yKHN0dWRlbnRfdCgzLCAwLCAyLjUpLCBjbGFzcyA9ICJzaWdtYSIpLAojICAgcHJpb3IoZXhwb25lbnRpYWwoMC41KSwgY2xhc3MgPSAic2RncCIpLAojICkKCgptMiA8LSBicm0oCiAgICBmb3JtdWxhID0gbG9nX3BtMl81IH4gZ3AoeCwgeSwgaz0xNSkgICsKICAgICAgcyhtZWFuX3RlbXBfYywgaz01KSArIAogICAgICBzKG1lYW5fY3VycmVudF9odW1pZGl0eSwgaz01KSArCiAgICAgIHMocG9wX2RlbnNpdHlfa20yLCBrPTUpICsKICAgICAgcyhidWlsZGluZ19jb3ZlcmFnZV9wY3QsIGs9NSkgKwogICAgICBzKGRpc3RfdG9fcm9hZF9tLCBrPTUpICsKICAgICAgc2luX2RveTEgKyBjb3NfZG95MSArCiAgICAgIHNpbl9kb3kyICsgY29zX2RveTIgKwogICAgICBzaW5fZG95MyArIGNvc19kb3kzLAogICAgZGF0YSA9IGFxX21vZGVsX2RhdGEsCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpLAogICAgI3ByaW9yID0gcHJpb3JzLAogICAgY2hhaW5zID0gNCwgY29yZXMgPSA0LAogICAgYmFja2VuZCA9ICJjbWRzdGFuciIKICApCgpzdW1tYXJ5KG0yKQpjb25kaXRpb25hbF9lZmZlY3RzKG0yKQpwcF9jaGVjayhtMikKcGxvdChtMikKCgpgYGAKUHJlZGljdGlvbnMgYnkgc3BhY2UgYW5kIHRpbWUKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CgojZmlyc3Qgd2UgbmVlZCBhIHByZWRpY3Rpb24gZGF0YWZyYW1lIHdpdGggYWxsIG9mIHRoZSBjb3ZhcmlhdGUgZGF0YQoKI2V4dHJhY3QgbW9udGggZnJvbSBkYXRlIHZhcmlhYmxlCmFxX21vZGVsX2RhdGEgPC0gYXFfbW9kZWxfZGF0YSAgJT4lCiAgbXV0YXRlKG1vbnRoID0gbHVicmlkYXRlOjptb250aChhcy5EYXRlKG1lYW5fZG95LCBvcmlnaW4gPSAiMjAxOS0xMi0zMSIpKSkKCiNjYWxjdWxhdGUgbW9udGhseSBtZWFucwptb250aGx5X21lYW5zIDwtIGFxX21vZGVsX2RhdGEgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIHN1bW1hcmlzZSgKICAgIG1lYW5fdGVtcF9jID0gbWVhbihtZWFuX3RlbXBfYywgbmEucm0gPSBUUlVFKSwKICAgIG1lYW5fY3VycmVudF9odW1pZGl0eSA9IG1lYW4obWVhbl9jdXJyZW50X2h1bWlkaXR5LCBuYS5ybSA9IFRSVUUpCiAgKQoKI05vIGRhdGEgY29sbGVjdGlvbiBpbiBBcHJpbCAtIGhlcmUgd2Ugd2lsbCBqdXN0IGludGVycG9sYXRlCiNjYW4gZG8gYmV0dGVyIGxhdGVyLi4uCm1hcmNoX3RlbXAgPC0gbW9udGhseV9tZWFucyAlPiUgZmlsdGVyKG1vbnRoID09IDMpICU+JSBwdWxsKG1lYW5fdGVtcF9jKQptYXlfdGVtcCA8LSBtb250aGx5X21lYW5zICU+JSBmaWx0ZXIobW9udGggPT0gNSkgJT4lIHB1bGwobWVhbl90ZW1wX2MpCmFwcmlsX3RlbXAgPC0gKG1hcmNoX3RlbXAgKyBtYXlfdGVtcCkgLyAyCgptYXJjaF9odW1pZGl0eSA8LSBtb250aGx5X21lYW5zICU+JSBmaWx0ZXIobW9udGggPT0gMykgJT4lIHB1bGwobWVhbl9jdXJyZW50X2h1bWlkaXR5KQptYXlfaHVtaWRpdHkgPC0gbW9udGhseV9tZWFucyAlPiUgZmlsdGVyKG1vbnRoID09IDUpICU+JSBwdWxsKG1lYW5fY3VycmVudF9odW1pZGl0eSkKYXByaWxfaHVtaWRpdHkgPC0gKG1hcmNoX2h1bWlkaXR5ICsgbWF5X2h1bWlkaXR5KSAvIDIKCiNhZGQgdGhlc2UgaW50byB0aGUgcHJlZGljdGlvbiBkYXRhZnJhbWUKbW9udGhseV9tZWFucyA8LSBtb250aGx5X21lYW5zICU+JQogIGFkZF9yb3cobW9udGg9NCwgCiAgICAgICAgICBtZWFuX3RlbXBfYyA9IGFwcmlsX3RlbXAsCiAgICAgICAgICBtZWFuX2N1cnJlbnRfaHVtaWRpdHkgPSBhcHJpbF9odW1pZGl0eSkgJT4lCiAgYXJyYW5nZShtb250aCkKCiNzZXRfdXAgcHJlZGljdGlvbiBkYXRlIGZyYW1lCm5kX20yIDwtIG13XzEwMG1fZ3JpZF9zZiAlPiUKICBtdXRhdGUoeCA9IHN0X2Nvb3JkaW5hdGVzKHN0X2NlbnRyb2lkKC4pKVssIDFdLAogICAgICAgICB5ID0gc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQoLikpWywgMl0pICU+JQogIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUKICByZW5hbWUocG9wX2RlbnNpdHkgPSAxKSAlPiUKICBtdXRhdGUocG9wX2RlbnNpdHlfa20yID0gcG9wX2RlbnNpdHkgLyAwLjAxKQoKI2dldCB0aGUgZmlyc3QgZGF5IG9mIGVhY2ggbW9udGggZm9yIHByZWRpY3Rpb24KZmlyc3RfZGF5cyA8LSB5bWQocGFzdGUwKCIyMDIwLSIsIHNwcmludGYoIiUwMmQiLCAxOjEyKSwgIi0wMSIpKQpmaXJzdF9kYXlfZG95IDwtIHlkYXkoZmlyc3RfZGF5cykKCiNjYWxjdWxhdGUgRm91cmllciB0ZXJtcwpmaXJzdF9kYXlfc2Vhc29uYWxpdHkgPC0gdGliYmxlKAogIG1lYW5fZG95ID0gZmlyc3RfZGF5X2RveSwKICBzaW5fZG95MSA9IHNpbigyICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgY29zX2RveTEgPSBjb3MoMiAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIHNpbl9kb3kyID0gc2luKDQgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBjb3NfZG95MiA9IGNvcyg0ICogcGkgKiBtZWFuX2RveSAvIDM2NS4yNSksCiAgc2luX2RveTMgPSBzaW4oNiAqIHBpICogbWVhbl9kb3kgLyAzNjUuMjUpLAogIGNvc19kb3kzID0gY29zKDYgKiBwaSAqIG1lYW5fZG95IC8gMzY1LjI1KSwKICBkYXRlID0gZmlyc3RfZGF5cwopICU+JQogIG11dGF0ZShtb250aCA9IGx1YnJpZGF0ZTo6bW9udGgoYXMuRGF0ZShtZWFuX2RveSwgb3JpZ2luID0gIjIwMTktMTItMzEiKSkpICU+JQogIGxlZnRfam9pbihtb250aGx5X21lYW5zKQoKbmRfbTIgPC0gbmRfbTIgJT4lCiAgY3Jvc3NpbmcoZmlyc3RfZGF5X3NlYXNvbmFsaXR5KQoKI3Rha2UgcG9zdGVyaW9yIGRyYXdzIC0gbm90ZSBzdG9yaW5nIGFzIGFuIHJ2YXJzIG9iamVjdCBmb3IgZWZmaWNpZW5jeQptMl9kcmF3cyA8LSBhZGRfZXByZWRfcnZhcnMob2JqZWN0ID0gbTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gbmRfbTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZHJhd3MgPSAyMDApICNub3RlIGNhbiBvbmx5IG1hbmFnZSB0aGlzIHdpdGhvdXQgY3Jhc2hpbmcgY29tcHV0ZXIhCgojbm93IGV4dHJhY3QgdGhlIHN1bW1hcnkgbWVhbiBhbmQgc2QgZm9yIGVhY2ggbW9udGgtZ3JpZCBjZWxsIGNvbWJpbmF0aW9uCm0yX2VwcmVkX2FycmF5IDwtIHBvc3Rlcmlvcjo6ZHJhd3Nfb2YobTJfZHJhd3MkLmVwcmVkKQoKI2NvbXB1dGUgcG9zdGVyaW9yIG1lYW5zIHBlciBsb2NhdGlvbgptMl9kcmF3cyQuZXByZWRfbWVhbiA8LSBjb2xNZWFucyhtMl9lcHJlZF9hcnJheSkKCiNjb21wdXRlIHBvc3RlcmlvciBzZCBwZXIgbG9jYXRpb24KbTJfZHJhd3MkLmVwcmVkX3NkIDwtIGFwcGx5KGVwcmVkX2FycmF5LCAyLCBzZCkKCm0yX3N1bSA8LSBtMl9kcmF3cyAlPiUgCiAgc2VsZWN0KGdyaWRfaWQsIHgsIHksIGRhdGUsIG1vbnRoLCAuZXByZWRfbWVhbiwgLmVwcmVkX3NkKQoKCiNwbG90IHByZWRpY3Rpb25zCm0yX3N1bSAlPiUgIAogIG11dGF0ZShkYXRlID0gbW9udGgoZGF0ZSwgbGFiZWwgPSBUUlVFKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fdGlsZShhZXMoeCA9IHgsIHk9eSwgZmlsbD0uZXByZWRfbWVhbikpICsKICBnZW9tX3NmKGRhdGEgPSBzY2FsZV83Ml9jbHVzdGVycywgY29sb3VyPSJncmV5NzgiLCBmaWxsPU5BKSArCiAgI2dlb21fc2YoZGF0YSA9IG1haW5fcm9hZHNfY3JvcHBlZCwgY29sb3VyPSJ3aGl0ZSIpICsgI3JvYWRzIGxvb2tpbmcgYSBiaXQgbWVzc3kgd2hlbiBwbG90dGVkIC0gd29yayBvbiB0aGlzLgogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKwogIGZhY2V0X3dyYXAoZGF0ZX4uKSArCiAgbGFicyh0aXRsZSA9ICJMb2coUE0yLjUpIGV4cG9zdXJlIiwKICAgICAgIHg9IiIsCiAgICAgICB5PSIiLAogICAgICAgY2FwdGlvbiA9ICJXaGl0ZSBib3VuZGFyaWVzIGFyZSBTQ0FMRSBzdHVkeSBjbHVzdGVycyIpICsKICB0aGVtZV9nZ2Rpc3QoKSArCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPU5BLCBjb2xvdXI9ImdyZXk3OCIpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXk3OCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSkKCiNwbG90IHNkCm0yX3N1bSAlPiUgIAogIG11dGF0ZShkYXRlID0gbW9udGgoZGF0ZSwgbGFiZWwgPSBUUlVFKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fdGlsZShhZXMoeCA9IHgsIHk9eSwgZmlsbD0uZXByZWRfc2QpKSArCiAgZ2VvbV9zZihkYXRhID0gc2NhbGVfNzJfY2x1c3RlcnMsIGNvbG91cj0iZ3JleTc4IiwgZmlsbD1OQSkgKwogICNnZW9tX3NmKGRhdGEgPSBtYWluX3JvYWRzX2Nyb3BwZWQsIGNvbG91cj0id2hpdGUiKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gIkYiKSArCiAgZmFjZXRfd3JhcChkYXRlfi4pICsKICBsYWJzKHRpdGxlID0gIkxvZyhQTTIuNSkgZXhwb3N1cmUiLAogICAgICAgeD0iIiwKICAgICAgIHk9IiIsCiAgICAgICBjYXB0aW9uID0gIldoaXRlIGJvdW5kYXJpZXMgYXJlIFNDQUxFIHN0dWR5IGNsdXN0ZXJzIikgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9TkEsIGNvbG91cj0iZ3JleTc4IiksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleTc4IiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpKQoKYGBgCgpTYW1wbGUgY29vcmRpbmF0ZXMsIGFuZCBwbG90IG92ZXIgdGltZQoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KCiNzYW1wbGUgY29vcmRpbmF0ZSBwb2ludHMKI3dpbGwgc29ydCBvdXQgdGhlIHNtYWxsIG51bWJlciBsYXRlcgpzZXQuc2VlZCgxMjMpCnNhbXBsZWRfcG9pbnRzX20yIDwtIGFxX21vZGVsX2RhdGEgJT4lCiAgc2FtcGxlX24oNTApICU+JQogIHNlbGVjdCh4LCB5LCBtZWFuX3RlbXBfYywgbWVhbl9jdXJyZW50X2h1bWlkaXR5LCBwb3BfZGVuc2l0eV9rbTIsIGJ1aWxkaW5nX2NvdmVyYWdlX3BjdCwgZGlzdF90b19yb2FkX20sIGdyaWRfaWQsIGxvZ19wbTJfNSkKCiNnZW5lcmF0ZSBET1kgMOKAkzM2NSBhbmQgY2FsY3VsYXRlIEZvdXJpZXIgdGVybXMKZG95X2dyaWQgPC0gdGliYmxlKGRveSA9IHNlcSgwLDM2NSwgYnk9MSkpICU+JQogIG11dGF0ZSgKICAgIHNpbl9kb3kxID0gc2luKDIgKiBwaSAqIGRveSAvIDM2NSksCiAgICBjb3NfZG95MSA9IGNvcygyICogcGkgKiBkb3kgLyAzNjUpLAogICAgc2luX2RveTIgPSBzaW4oNCAqIHBpICogZG95IC8gMzY1KSwKICAgIGNvc19kb3kyID0gY29zKDQgKiBwaSAqIGRveSAvIDM2NSksCiAgICBzaW5fZG95MyA9IHNpbig2ICogcGkgKiBkb3kgLyAzNjUpLAogICAgY29zX2RveTMgPSBjb3MoNiAqIHBpICogZG95IC8gMzY1KQogICkKCiNleHBhbmQgZ3JpZCBhY3Jvc3Mgc2FtcGxlZCBsb2NhdGlvbnMKcHJlZGljdGlvbl9kZl9tMiA8LSBzYW1wbGVkX3BvaW50c19tMiAlPiUKICBjcm9zc2luZyhkb3lfZ3JpZCkKCiNhZGQgcHJlZGljdGlvbnMKcHJlZHNfbTIgPC0gYWRkX2VwcmVkX2RyYXdzKG9iamVjdCA9IG0yLCBuZXdkYXRhID0gcHJlZGljdGlvbl9kZl9tMiwgbmRyYXdzID0gMTAwKQoKI29ic2VydmVkIGRhdGEgZm9yIHBsb3R0aW5nCm9ic2VydmVkX2RhdGEgPC0gYXFfbW9kZWxfZGF0YSAlPiUKICBzZWxlY3QobWVhbl9kb3ksIGxvZ19wbTJfNSkgJT4lCiAgbXV0YXRlKG1lYW5fZG95ID0gcm91bmQobWVhbl9kb3kpKQoKI3Bsb3QKcHJlZHNfbTIgJT4lCiAgdW5ncm91cCgpICU+JQogIGdncGxvdChhZXMoeD1kb3kpKSArCiAgc3RhdF9saW5lcmliYm9uKGFlcyh5PS5lcHJlZCksIC53aWR0aD0wLjk1KSArIAogIGdlb21faml0dGVyKGRhdGEgPSBvYnNlcnZlZF9kYXRhLCBhZXMoeCA9IG1lYW5fZG95LCB5ID0gbG9nX3BtMl81KSwKICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgYWxwaGEgPSAwLjYsIHdpZHRoID0gMC41LCBoZWlnaHQgPSAwLjAsIHNpemUgPSAxLjIpICsKICBzY2FsZV9maWxsX2JyZXdlcigpICsKICBsYWJzKHRpdGxlID0gIk1vZGVsLWVzdGltYXRlZCBsb2coUE0yLjUpIHdpdGggZW1waXJpY2FsIG1lYXN1cmVtZW50cyIsCiAgICAgICBzdWJ0aXRsZSA9ICJNb2RlbCBwcmVkaWN0aW9ucyB3aXRoIDk1JSBDckkgYW5kIG9ic2VydmVkIGRhdGEgcG9pbnRzIiwKICAgICAgIHggPSAiRGF5IG9mIHllYXIiLAogICAgICAgeSA9ICJsb2coUE0yLjUpIiwKICAgICAgIGNhcHRpb24gPSAiTW9kZWxsZWQgZXN0aW1hdGVzIHJlc3RyaWN0ZWQgdG8gd2l0aGluIGNsdXN0ZXJzIikgKwogIHRoZW1lX2dnZGlzdCgpICsKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5NzgiKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgoKCmBgYAoKCkNvbXBhcmUgbW9kZWxzLCB1c2luZyBMT08gQ1YKCmBgYHtyfQoKbGlicmFyeShsb28pCgpsb29fbTEgPC0gbG9vKG0xKQpsb29fbTIgPC0gbG9vKG0yKQoKbG9vX2NvbXBhcmUobG9vX20xLCBsb29fbTIpCmBgYAoKClRPRE8KCiAtIFBSSU9SUwogLSBPVEhFUiBDT1ZBUklBVEVTCiAtIENPTVBBUkUgTU9ERUxTIFdJVEggRElGRkVSRU5UIEJBU0lTIEZVTkNUSU9OUyBGT1IgR1AgQU5EIFNQTElORVMKIC0gRVhDRUVEQU5DRVMKIC0gTElOSyBUTyBNVEIgSU5GRUNUSU9OIFBSRVZBTEVOQ0UgREFUQSwgQU5EIE1PREVMCg==